{ "cells": [ { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# Sales commissions forecast\n", "\n", "## Try me\n", " [![Open In Colab](../../_static/colabs_badge.png)](https://colab.research.google.com/github/ffraile/operations-research-notebooks/blob/main/docs/source/Simulation/Solved/Sales%20commissions%20forecast.ipynb)[![Binder](../../_static/binder_badge.png)](https://mybinder.org/v2/gh/ffraile/operations-research-notebooks/main?labpath=docs%2Fsource%2FSimulation%2FSolved%2FSales%20commissions%20forecast.ipynb)\n", "\n", "## Problem Definition\n", "A company with 5 sales managers wants to provision budget to pay sales commissions to sales managers. The company applies a commission rate based on the percentage of target sales obtained, given by the following table:\n", "\n", "| Sales / Target ratio \t| Commission Rate \t|\n", "|----------------------\t|-----------------\t|\n", "| 0-90 % \t| 2% \t|\n", "| 90-100% | 3% \t|\n", "| >= 100% \t| 4% \t|\n" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "Each salesman will be compensated with the commission rate times the total sales obtained. The following table shows the target sales for the five sales managers:\n", "\n", "| Sales Manager \t| Sales Target (€) \t|\n", "|---------------\t|------------------\t|\n", "| 1 \t| 100,000 \t|\n", "| 2 \t| 200,000 \t|\n", "| 3 \t| 75,000 \t|\n", "| 4 \t| 400,000 \t|\n", "| 5 \t| 500,000 \t|\n", "\n" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "**a)** Estimate the budget for sales commissions the company has to pay in the scenario where all sales managers get exactly the 100% of the sales target (naive approach).\n", "\n", "**b)** The company has a historical record of sales for the five sales managers and from this record, it can estimate that the Percent to Plan (The ratio between the actual sales and the sales target) can be modelled by a normal distribution with a mean of 100% and standard deviation of 10%. Use this insight to estimate the budget for sales commissions using a MonteCarlo distribution." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Solution\n", "**a)** In the requested scenario, the sales obtained by each sales manager are represented in the table below:\n", "\n", "\n", "| Sales Manager \t| Sales Target (€) \t| Actual Sales (€) \t| Percent to Plan (%) \t| Commission Rate (€) \t| Commission Amount (€) \t|\n", "|---------------\t|------------------\t|------------------\t|---------------------\t|---------------------\t|-----------------------\t|\n", "| 1 \t| 100,000 \t| 100,000 \t| 100 \t| 4 \t| 4,000 \t|\n", "| 2 \t| 200,000 \t| 200,000 \t| 100 \t| 4 \t| 8,000 \t|\n", "| 3 \t| 75,000 \t| 75,000 \t| 100 \t| 4 \t| 3,000 \t|\n", "| 4 \t| 400,000 \t| 400,000 \t| 100 \t| 4 \t| 16,000 \t|\n", "| 5 \t| 500,000 \t| 500,000 \t| 100 \t| 4 \t| 20,000 \t|\n", "\n", "The total budget for sales commission can be obtained with the summation of the last column (51,000€)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "**b)** In order to estimate the budget using Montecarlo, we are going to use the Python numpy package to calculate the probability distribution." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "First we import the libraries we are going to use:" ] }, { "cell_type": "code", "execution_count": 45, "metadata": { "slideshow": { "slide_type": "fragment" }, "pycharm": { "is_executing": false } }, "outputs": [], "source": [ "\n", "import pandas as pd\n", "import numpy as np\n" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Then we initialise the data needed to model the problem" ] }, { "cell_type": "code", "execution_count": 46, "metadata": { "slideshow": { "slide_type": "fragment" }, "pycharm": { "is_executing": false } }, "outputs": [], "source": [ "\n", "avg = 1\n", "std_dev = .1\n", "num_simulations = 1000\n", "\n", "sales_target_values = np.array([100000, 200000, 75000, 400000, 500000])\n", "\n", "# Define a function to calculate the commission rate depending on the rate to target\n", "def calc_com_rate(x):\n", " if x <= 0.9:\n", " return 0.02\n", " elif x <= 1:\n", " return 0.03\n", " else:\n", " return 0.04\n", " \n", "# You can also use a lambda:\n", "# calc_com_rate = lambda x: 0.02 if x <= 0.9 else 0.03 if x <= 0.99 else 0.04 \n", "\n", "# Vectorize the function so that we can apply it to vectors and matrices\n", "v_calc_com_rate = np.vectorize(calc_com_rate)\n", "\n", "# Define a list to keep all the results from each simulation that we want to analyze\n", "all_stats = np.zeros((num_simulations, 3))\n", "\n", "\n", "\n" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Now we run the simulations in a for loop:" ] }, { "cell_type": "code", "execution_count": 47, "metadata": { "slideshow": { "slide_type": "fragment" }, "pycharm": { "is_executing": false } }, "outputs": [], "source": [ "# Loop through simulations\n", "for i in range(num_simulations):\n", "\n", " # Choose random inputs for the sales targets and percent to target\n", " pct_to_target = np.random.normal(avg, std_dev, len(sales_target_values))\n", "\n", " #Calculate actual sales\n", " sales = pct_to_target*sales_target_values\n", " \n", " # Determine the commissions rate and calculate it\n", " commission_rate = v_calc_com_rate(np.array(pct_to_target))\n", "\n", " # Calculate the commission\n", " commission = sales*commission_rate\n", " \n", " # We want to track sales,commission amounts and sales targets over all the simulations\n", " # Sum values among sales managers and calculate the mean commission rate\n", " all_stats[i,:] = [np.sum(sales),\n", " np.sum(commission),\n", " np.mean(commission_rate)]\n", "\n", "\n", "results_df = pd.DataFrame.from_records(all_stats, columns=['Sales',\n", " 'Commission_Amount',\n", " 'Commission_Rate'])" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Finally, we represent the results and calculate the confidence interval:" ] }, { "cell_type": "code", "execution_count": 48, "metadata": { "slideshow": { "slide_type": "fragment" }, "pycharm": { "is_executing": false } }, "outputs": [ { "data": { "text/plain": " Sales Commission_Amount Commission_Rate\ncount 1.000000e+03 1000.000000 1000.000000\nmean 1.275014e+06 44052.103207 0.033898\nstd 6.787145e+04 6867.089676 0.003249\nmin 1.074120e+06 23942.116488 0.024000\n25% 1.229842e+06 39561.533879 0.032000\n50% 1.275006e+06 44543.493621 0.034000\n75% 1.317589e+06 49169.062538 0.036000\nmax 1.478058e+06 58539.162650 0.040000", "text/html": "
\n\n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
SalesCommission_AmountCommission_Rate
count1.000000e+031000.0000001000.000000
mean1.275014e+0644052.1032070.033898
std6.787145e+046867.0896760.003249
min1.074120e+0623942.1164880.024000
25%1.229842e+0639561.5338790.032000
50%1.275006e+0644543.4936210.034000
75%1.317589e+0649169.0625380.036000
max1.478058e+0658539.1626500.040000
\n
" }, "metadata": {}, "output_type": "execute_result", "execution_count": 48 } ], "source": [ "results_df.describe()" ] }, { "cell_type": "code", "execution_count": 49, "metadata": { "pycharm": { "is_executing": false } }, "outputs": [ { "name": "stderr", "text": [ "c:\\users\\ffraile\\appdata\\local\\programs\\python\\python37\\lib\\site-packages\\pandas\\plotting\\_matplotlib\\tools.py:307: MatplotlibDeprecationWarning: \n", "The rowNum attribute was deprecated in Matplotlib 3.2 and will be removed two minor releases later. Use ax.get_subplotspec().rowspan.start instead.\n", " layout[ax.rowNum, ax.colNum] = ax.get_visible()\n", "c:\\users\\ffraile\\appdata\\local\\programs\\python\\python37\\lib\\site-packages\\pandas\\plotting\\_matplotlib\\tools.py:307: MatplotlibDeprecationWarning: \n", "The colNum attribute was deprecated in Matplotlib 3.2 and will be removed two minor releases later. Use ax.get_subplotspec().colspan.start instead.\n", " layout[ax.rowNum, ax.colNum] = ax.get_visible()\n", "c:\\users\\ffraile\\appdata\\local\\programs\\python\\python37\\lib\\site-packages\\pandas\\plotting\\_matplotlib\\tools.py:313: MatplotlibDeprecationWarning: \n", "The rowNum attribute was deprecated in Matplotlib 3.2 and will be removed two minor releases later. Use ax.get_subplotspec().rowspan.start instead.\n", " if not layout[ax.rowNum + 1, ax.colNum]:\n", "c:\\users\\ffraile\\appdata\\local\\programs\\python\\python37\\lib\\site-packages\\pandas\\plotting\\_matplotlib\\tools.py:313: MatplotlibDeprecationWarning: \n", "The colNum attribute was deprecated in Matplotlib 3.2 and will be removed two minor releases later. Use ax.get_subplotspec().colspan.start instead.\n", " if not layout[ax.rowNum + 1, ax.colNum]:\n" ], "output_type": "stream" }, { "data": { "text/plain": "
", "image/png": "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\n" }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "hist = results_df.hist(bins=100)" ] }, { "cell_type": "code", "execution_count": 50, "metadata": { "slideshow": { "slide_type": "subslide" }, "pycharm": { "is_executing": false } }, "outputs": [ { "name": "stdout", "text": [ "95% confidence interval is: (43626.697262449656, 44477.5091506711)\n", "or\n", "(43626.697262449656, 44477.5091506711)\n" ], "output_type": "stream" } ], "source": [ "import scipy.stats as st\n", "#Calculate the 95% confidence interval\n", "\n", "# We collect the results from the data frame\n", "a = np.array(results_df['Commission_Amount'])\n", "\n", "\n", "# loc is used to center the distribution at mean of array\n", "# scale is used to scale the distribution according to the standard error \n", "# of the mean (st.sem)\n", "arr_standard_dev = np.std(a)/(len(a)**0.5)\n", "arr_mean = np.mean(a)\n", "interval = (st.norm.ppf(0.025, loc= arr_mean, scale=arr_standard_dev), st.norm.ppf(0.975, loc= arr_mean, scale=arr_standard_dev))" ] }, { "cell_type": "code", "execution_count": 51, "metadata": { "slideshow": { "slide_type": "skip" }, "pycharm": { "is_executing": false } }, "outputs": [ { "data": { "text/plain": " Sales Commission_Amount Commission_Rate\ncount 1.000000e+03 1000.000000 1000.000000\nmean 1.274653e+06 43849.666014 0.033772\nstd 6.770009e+04 6868.545178 0.003330\nmin 1.070847e+06 22201.173382 0.020000\n25% 1.228111e+06 39223.966965 0.032000\n50% 1.275056e+06 44283.089045 0.034000\n75% 1.320497e+06 49146.611184 0.036000\nmax 1.469480e+06 58207.805777 0.040000", "text/html": "
\n\n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
SalesCommission_AmountCommission_Rate
count1.000000e+031000.0000001000.000000
mean1.274653e+0643849.6660140.033772
std6.770009e+046868.5451780.003330
min1.070847e+0622201.1733820.020000
25%1.228111e+0639223.9669650.032000
50%1.275056e+0644283.0890450.034000
75%1.320497e+0649146.6111840.036000
max1.469480e+0658207.8057770.040000
\n
" }, "metadata": {}, "output_type": "execute_result", "execution_count": 51 } ], "source": [ "import pandas as pd\n", "import numpy as np\n", "\n", "avg = 1\n", "std_dev = .1\n", "num_reps = 500\n", "num_simulations = 1000\n", "\n", "sales_target_values = np.array([100000, 200000, 75000, 400000, 500000])\n", "\n", "# Define a lambda function to calculate the ratio\n", "calc_com_rate = lambda x: 0.02 if x <= 0.9 else 0.03 if x <= 0.99 else 0.04 \n", "v_calc_com_rate = np.vectorize(calc_com_rate)\n", "\n", "# Choose random inputs for the sales targets and percent to target, \n", "# this time create a matrix with as many rows as simulations\n", "pct_to_target = np.random.normal(avg, std_dev, (num_simulations, len(sales_target_values)))\n", "\n", "# Reshape the sales target values into a matrix of adequate size\n", "stv = np.broadcast_to(sales_target_values, (num_simulations, len(sales_target_values)))\n", "\n", "# Calculate the sales applying the ratio\n", "sales = pct_to_target*stv\n", "\n", "# Calculate commission rate\n", "commission_rate = v_calc_com_rate(pct_to_target)\n", "\n", "# And commission\n", "commission = sales*commission_rate\n", "\n", "# Sum values among sales managers and calculate the mean commission rate\n", "all_stats = [np.sum(sales, axis=1), np.sum(commission, axis=1), np.mean(commission_rate, axis=1)]\n", "\n", "results_df = pd.DataFrame.from_records(np.transpose(all_stats), columns=['Sales',\n", " 'Commission_Amount',\n", " 'Commission_Rate'])\n", "\n", "results_df.describe()\n" ] } ], "metadata": { "celltoolbar": "Slideshow", "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.7.4" }, "pycharm": { "stem_cell": { "cell_type": "raw", "source": [], "metadata": { "collapsed": false } } } }, "nbformat": 4, "nbformat_minor": 2 }